import { useRef, useState } from 'react';

function getUsername(): Promise<string> {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // const name = '@name' + Math.random();
      // resolve(name);
      console.log('--getUsername--触发--');
      resolve('@name' + Math.random());
    }, 1000);
  });
}

//-------------useRequest----------------
class Fetch {
  fn: Function;
  data: any;
  loading: boolean = false;
  constructor(fn: Function) {
    this.fn = fn;
  }
  run() {
    this.loading = true;
    return this.fn()
      .then((res: any) => {
        this.data = res;
        // 会 return 一个 新的 Promise 实例
      })
      .finally(() => {
        this.loading = false;
      });
  }
}

function useRequest(fn: Function) {
  const fetchInstanceRef = useRef<Fetch>();
  if (!fetchInstanceRef.current) {
    fetchInstanceRef.current = new Fetch(fn);
  }
  return {
    loading: fetchInstanceRef.current.loading,
    data: fetchInstanceRef.current.data,
    run: fetchInstanceRef.current.run.bind(fetchInstanceRef.current),
  };
}

function PrincipleAnalysis() {
  // const { loading: loading2, data: data2, run: run2 } = useRequest(getUsername);
  const [, setUpdate] = useState(0);

  const fetchInstanceRef = useRef<Fetch>();
  if (!fetchInstanceRef.current) {
    fetchInstanceRef.current = new Fetch(getUsername);
  }

  // useState,useReducer,hooks中定义的变量没有改变时，函数不会执行。
  console.log('PrincipleAnalysis 函数执行---');

  const handleRun = () => {
    // setUpdate(Math.random()); //强制刷新PrincipleAnalysis
    fetchInstanceRef.current!.run().finally(() => {
      // setUpdate(Math.random());
    });
  };

  return (
    <div>
      <h3>原理分析2:拆解useRequest</h3>
      <p>本来useRef.current 中的值就不能直接用来渲染，因为useRef.current中的值改变，函数不会重新执行。 </p>
      <p>硬要显示useRef.current 中的最新值，就得在更新useRef.current 中的值的时候，通过useState使函数重新执行。</p>

      <div style={{ marginTop: '30px' }}>
        <p>useRequest---=data:{fetchInstanceRef.current!.data}</p>
        <button disabled={fetchInstanceRef.current!.loading} onClick={handleRun}>
          {fetchInstanceRef.current!.loading ? 'loading' : 'run'}
        </button>
      </div>
    </div>
  );
}

export default PrincipleAnalysis;